package cn.talk.doodle.util;

import cn.talk.doodle.ability.base.DoodleActivity;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.agp.components.AttrHelper;
import ohos.agp.render.*;
import ohos.agp.utils.Matrix;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import ohos.utils.net.Uri;

import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;

public class ImageUtils {

    /**
     * @param source  pixelMap to crop
     * @param desRect desired area to save
     * @return the cropped pixelMap
     */
    public static PixelMap cropPixelMap(PixelMap source, Rect desRect) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(desRect.width, desRect.height);
        PixelMap resultPixelMap = PixelMap.create(source, desRect, initializationOptions);
        return resultPixelMap;
    }

    /**
     * @param path    image path
     * @param desRect desired area to save
     * @return the cropped pixelMap
     */
    public static PixelMap cropPixelMap(String path, Rect desRect) {
        PixelMap source = new PhotoDecode.Builder().build().commonDecodePhoto(path);
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = new Size(desRect.width, desRect.height);
        PixelMap resultPixelMap = PixelMap.create(source, desRect, initializationOptions);
        return resultPixelMap;
    }
    //todo source.getImageInfo() 数值为空 还是用全屏的大小吧？
    /**
     * @param source pixelMap to rotate
     * @param degree desired degree to rotate
     * @return the rotated pixelMap,the returned pixelMap may be cropped if the the width of source is not equal to height
     */
    public static PixelMap rotatePixelMapByMatrix(PixelMap source, float degree, Context context) {

        if (source != null){
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            Size sourceSize;
            if (null != source.getImageInfo()){
                sourceSize = source.getImageInfo().size;
            }else{
                Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
                int screenWidth = display.getRealAttributes().width;
                int screenHeight = display.getRealAttributes().height;
                sourceSize = new Size(screenWidth, screenHeight);
            }
            initializationOptions.size = new Size(sourceSize.width, sourceSize.height);
            PixelMap resultPixelMap = PixelMap.create(initializationOptions);
            Texture texture = new Texture(resultPixelMap);
            Canvas canvas = new Canvas(texture);
            canvas.save();
            Matrix matrix = new Matrix();
            matrix.postRotate(degree, sourceSize.width / 2f, sourceSize.height / 2f);
            canvas.setMatrix(matrix);
            PixelMapHolder holder = new PixelMapHolder(source);
            canvas.drawPixelMapHolder(holder, 0, 0, new Paint());
            canvas.restore();
            source.release();
            source = null;
            return resultPixelMap;
        }

        return source;


    }

    /**
     * @param source pixelMap to rotate
     * @param degree desired degree to rotate
     * @return the rotated pixelMap
     */
    public static PixelMap rotatePixelMapByDecoding(PixelMap source, float degree) {
        ImagePacker packer = ImagePacker.create();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
        packingOptions.quality = 100;
        packer.initializePacking(byteArrayOutputStream, packingOptions);
        packer.addImage(source);
        packer.finalizePacking();
        packer.release();

        ImageSource imageSource = ImageSource.create(byteArrayOutputStream.toByteArray(), new ImageSource.SourceOptions());
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        decodingOptions.rotateDegrees = degree;
        PixelMap resultPixelMap = imageSource.createPixelmap(decodingOptions);
        imageSource.release();
        source.release();
        source = null;
        return resultPixelMap;
    }


    /**
     * @param source       pixelMap to flip
     * @param isHorizontal horizontally flipped or not
     * @param isVertical   vertically flipped or not
     * @return the flipped pixelMap
     */
    public static PixelMap flipPixelMap(PixelMap source, boolean isHorizontal, boolean isVertical) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        Size sourceSize = source.getImageInfo().size;
        initializationOptions.size = sourceSize;
        PixelMap resultPixelMap = PixelMap.create(initializationOptions);
        Canvas canvas = new Canvas(new Texture(resultPixelMap));
        Matrix matrix = new Matrix();
        matrix.preScale(isHorizontal ? -1 : 1, isVertical ? -1 : 1);
        if (isHorizontal) {
            matrix.postTranslate(sourceSize.width, 0);
        }
        if (isVertical) {
            matrix.postTranslate(0, sourceSize.height);
        }
        canvas.setMatrix(matrix);
        PixelMapHolder holder = new PixelMapHolder(source);
        canvas.drawPixelMapHolder(holder, 0, 0, new Paint());
        source.release();
        source = null;
        return resultPixelMap;
    }

    /**
     * @param source pixelMap to change luminance
     * @param lum    desired lum
     * @return changed pixelMap亮度
     */
    public static PixelMap changePixelMapLuminance(PixelMap source, float lum) {
        Canvas canvas = new Canvas();
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = source.getImageInfo().size;
        PixelMap resultPixelMap = PixelMap.create(initializationOptions);
        canvas.setTexture(new Texture(resultPixelMap));
        PixelMapHolder holder = new PixelMapHolder(source);
        Paint paint = new Paint();
        ColorMatrix lumMatrix = new ColorMatrix();
        lumMatrix.setMatrix(new float[]{
                1, 0, 0, 0, lum,
                0, 1, 0, 0, lum,
                0, 0, 1, 0, lum,
                0, 0, 0, 1, 0
        });
        paint.setColorMatrix(lumMatrix);
        canvas.drawPixelMapHolder(holder, 0, 0, paint);
//        source.release();
//        source = null;
        return resultPixelMap;
    }


    /**
     * @param source     pixelMap to change saturation
     * @param saturation desired saturation
     * @return changed pixelMap饱和度
     */
    public static PixelMap changePixelMapSaturation(PixelMap source, float saturation) {
        Canvas canvas = new Canvas();
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = source.getImageInfo().size;
        PixelMap resultPixelMap = PixelMap.create(initializationOptions);
        canvas.setTexture(new Texture(resultPixelMap));
        PixelMapHolder holder = new PixelMapHolder(source);
        Paint paint = new Paint();
        ColorMatrix saturationMatrix = new ColorMatrix();
        saturationMatrix.setSaturation(saturation);
        paint.setColorMatrix(saturationMatrix);
        canvas.drawPixelMapHolder(holder, 0, 0, paint);
//        source.release();
//        source = null;
        return resultPixelMap;
    }

    /**
     * @param source   pixelMap to change contrast
     * @param contrast desired contrast
     * @return changed pixelMap对比度
     */
    public static PixelMap changePixelMapContrast(PixelMap source, float contrast) {
        Canvas canvas = new Canvas();
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = source.getImageInfo().size;
        PixelMap resultPixelMap = PixelMap.create(initializationOptions);
        canvas.setTexture(new Texture(resultPixelMap));
        PixelMapHolder holder = new PixelMapHolder(source);
        Paint paint = new Paint();
        ColorMatrix contrastMatrix = new ColorMatrix();
        contrastMatrix.setMatrix(new float[]{
                contrast, 0, 0, 0, 0,
                0, contrast, 0, 0, 0,
                0, 0, contrast, 0, 0,
                0, 0, 0, 1, 0
        });
        paint.setColorMatrix(contrastMatrix);
        canvas.drawPixelMapHolder(holder, 0, 0, paint);
//        source.release();
//        source = null;
        return resultPixelMap;
    }


    /**
     * @param source      pixelMap to change temperature
     * @param temperature desired temperature
     * @return changed pixelMap
     */
    public static PixelMap changePixelMapTemperature(PixelMap source, float temperature) {
        Canvas canvas = new Canvas();
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.size = source.getImageInfo().size;
        PixelMap resultPixelMap = PixelMap.create(initializationOptions);
        canvas.setTexture(new Texture(resultPixelMap));
        PixelMapHolder holder = new PixelMapHolder(source);
        Paint paint = new Paint();
        ColorMatrix temperatureMatrix = new ColorMatrix();
        temperatureMatrix.setMatrix(new float[]{
                1, 0, 0, 0, 0,
                0, ((1 + temperature) * 255) / 255f, 0, 0, 0,
                0, 0, ((1 + temperature) * 255) / 255, 0, 0,
                0, 0, 0, 1, 0}
        );
        paint.setColorMatrix(temperatureMatrix);
        canvas.drawPixelMapHolder(holder, 0, 0, paint);
//        source.release();
//        source = null;
        return resultPixelMap;
    }

    public static PixelMap createPixelMapFromUri(Uri mImageUri, Context context, DataAbilityHelper helper) {

        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        final int screenWidth = display.getRealAttributes().width;
        final int height = display.getRealAttributes().height;
        PixelMap selectedPic = null;
        FileDescriptor filedesc = null;
        try {
            filedesc = helper.openFile(mImageUri,"r");
            ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
            decodingOpts.desiredSize = new Size(screenWidth,height);
            ImageSource imageSource = ImageSource.create(filedesc,null);

            selectedPic = imageSource.createPixelmap(decodingOpts);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }


        return selectedPic;
    }

    public static PixelMap createPixelMapFromUriAndSize(Uri mImageUri, DataAbilityHelper helper, int width, int height) {

        PixelMap selectedPic = null;
        FileDescriptor filedesc = null;
        try {
            filedesc = helper.openFile(mImageUri,"r");
            ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
            decodingOpts.desiredSize = new Size(width,height);
            ImageSource imageSource = ImageSource.create(filedesc,null);

            selectedPic = imageSource.createPixelmap(decodingOpts);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }


        return selectedPic;
    }
}
